/*
 * @Author       : Bing Chen chenbing@iocharger.com
 * @Date         : 2025-01-21 16:09:28
 * @LastEditors  : Bing Chen chenbing@iocharger.com
 * @LastEditTime : 2025-03-15 13:00:42
 * @FilePath     : \openchaoji-corelib\shared\src\OpenChaoJi_gbt27930_a_encode.c
 * @Description  :
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include "../include/OpenChaoJi_shared.h"

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_A == CONFIG_YES)

/**
 * bs方法, 辅助进行字节流传输
 */
#include "bs.h"
#define bs_read     bs_read_le
#define bs_write    bs_write_le
#define bs_read_bytes     bs_read_bytes_le
#define bs_write_bytes    bs_write_bytes_le


/*********************************************************************************************************************************************/

/**
 * @function OpenChaoJi_gbt27930_a_msg_len
 * @brief 获取消息长度
 * @param pgi 消息类型
 * @return int 消息长度
 */
extern int OpenChaoJi_gbt27930_a_msg_len(struct OpenChaoJi_gbt27930_a_msg *msg)
{
    switch (msg->pid) {
    case OPENCHAOJI_GBT27930_A_PGN_CHM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CHM;
    case OPENCHAOJI_GBT27930_A_PGN_CRM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CRM;
    case OPENCHAOJI_GBT27930_A_PGN_CTS: return OPENCHAOJI_GBT27930_A_MSG_LEN_CTS;
    case OPENCHAOJI_GBT27930_A_PGN_CML: return OPENCHAOJI_GBT27930_A_MSG_LEN_CML;
    case OPENCHAOJI_GBT27930_A_PGN_CRO: return OPENCHAOJI_GBT27930_A_MSG_LEN_CRO;
    case OPENCHAOJI_GBT27930_A_PGN_CCS: return OPENCHAOJI_GBT27930_A_MSG_LEN_CCS;
    case OPENCHAOJI_GBT27930_A_PGN_CST: return OPENCHAOJI_GBT27930_A_MSG_LEN_CST;
    case OPENCHAOJI_GBT27930_A_PGN_CSD: return OPENCHAOJI_GBT27930_A_MSG_LEN_CSD;
    case OPENCHAOJI_GBT27930_A_PGN_CEM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CEM;

    case OPENCHAOJI_GBT27930_A_PGN_BHM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BHM;
    case OPENCHAOJI_GBT27930_A_PGN_BRM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BRM;
    case OPENCHAOJI_GBT27930_A_PGN_BCP: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCP;
    case OPENCHAOJI_GBT27930_A_PGN_BRO: return OPENCHAOJI_GBT27930_A_MSG_LEN_BRO;
    case OPENCHAOJI_GBT27930_A_PGN_BCL: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCL;
    case OPENCHAOJI_GBT27930_A_PGN_BCS: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCS;
    case OPENCHAOJI_GBT27930_A_PGN_BSM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSM;
    case OPENCHAOJI_GBT27930_A_PGN_BMV: return msg->msg.bmv.cellvolt_num * 2;
    case OPENCHAOJI_GBT27930_A_PGN_BMT: return msg->msg.bmt.tempera_num;
    case OPENCHAOJI_GBT27930_A_PGN_BSP: return msg->msg.bsp.res_num;
    case OPENCHAOJI_GBT27930_A_PGN_BST: return OPENCHAOJI_GBT27930_A_MSG_LEN_BST;
    case OPENCHAOJI_GBT27930_A_PGN_BSD: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSD;
    case OPENCHAOJI_GBT27930_A_PGN_BEM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BEM;
    default:
        return 0;
    }
}

/**
 * @function OpenChaoJi_gbt27930_a_msg_len_max
 * @brief 获取消息最大长度 (用于编码校验)
 * @param pgi 消息类型
 * @return int 消息最大长度
 */
extern int OpenChaoJi_gbt27930_a_msg_len_max(uint8_t pgi)
{
    switch (pgi) {
    case OPENCHAOJI_GBT27930_A_PGN_CHM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CHM;
    case OPENCHAOJI_GBT27930_A_PGN_CRM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CRM;
    case OPENCHAOJI_GBT27930_A_PGN_CTS: return OPENCHAOJI_GBT27930_A_MSG_LEN_CTS;
    case OPENCHAOJI_GBT27930_A_PGN_CML: return OPENCHAOJI_GBT27930_A_MSG_LEN_CML;
    case OPENCHAOJI_GBT27930_A_PGN_CRO: return OPENCHAOJI_GBT27930_A_MSG_LEN_CRO;
    case OPENCHAOJI_GBT27930_A_PGN_CCS: return OPENCHAOJI_GBT27930_A_MSG_LEN_CCS;
    case OPENCHAOJI_GBT27930_A_PGN_CST: return OPENCHAOJI_GBT27930_A_MSG_LEN_CST;
    case OPENCHAOJI_GBT27930_A_PGN_CSD: return OPENCHAOJI_GBT27930_A_MSG_LEN_CSD;
    case OPENCHAOJI_GBT27930_A_PGN_CEM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CEM;

    case OPENCHAOJI_GBT27930_A_PGN_BHM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BHM;
    case OPENCHAOJI_GBT27930_A_PGN_BRM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BRM;
    case OPENCHAOJI_GBT27930_A_PGN_BCP: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCP;
    case OPENCHAOJI_GBT27930_A_PGN_BRO: return OPENCHAOJI_GBT27930_A_MSG_LEN_BRO;
    case OPENCHAOJI_GBT27930_A_PGN_BCL: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCL;
    case OPENCHAOJI_GBT27930_A_PGN_BCS: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCS;
    case OPENCHAOJI_GBT27930_A_PGN_BSM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSM;
    case OPENCHAOJI_GBT27930_A_PGN_BMV: return OPENCHAOJI_GBT27930_A_MSG_LEN_BMV;
    case OPENCHAOJI_GBT27930_A_PGN_BMT: return OPENCHAOJI_GBT27930_A_MSG_LEN_BMT;
    case OPENCHAOJI_GBT27930_A_PGN_BSP: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSP;
    case OPENCHAOJI_GBT27930_A_PGN_BST: return OPENCHAOJI_GBT27930_A_MSG_LEN_BST;
    case OPENCHAOJI_GBT27930_A_PGN_BSD: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSD;
    case OPENCHAOJI_GBT27930_A_PGN_BEM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BEM;
    default:
        return 0;
    }
}

/**
 * @function OpenChaoJi_gbt27930_a_msg_len_min
 * @brief 获取消息最小长度 (用于解码校验)
 * @param pgi 消息类型
 * @return int 消息最小长度
 */
extern int OpenChaoJi_gbt27930_a_msg_len_min(uint8_t pgi)
{
    switch (pgi) {
    case OPENCHAOJI_GBT27930_A_PGN_CHM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CHM;
    case OPENCHAOJI_GBT27930_A_PGN_CRM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CRM;
    case OPENCHAOJI_GBT27930_A_PGN_CTS: return OPENCHAOJI_GBT27930_A_MSG_LEN_CTS;
    case OPENCHAOJI_GBT27930_A_PGN_CML: return OPENCHAOJI_GBT27930_A_MSG_LEN_CML;
    case OPENCHAOJI_GBT27930_A_PGN_CRO: return OPENCHAOJI_GBT27930_A_MSG_LEN_CRO;
    case OPENCHAOJI_GBT27930_A_PGN_CCS: return OPENCHAOJI_GBT27930_A_MSG_LEN_CCS;
    case OPENCHAOJI_GBT27930_A_PGN_CST: return OPENCHAOJI_GBT27930_A_MSG_LEN_CST;
    case OPENCHAOJI_GBT27930_A_PGN_CSD: return OPENCHAOJI_GBT27930_A_MSG_LEN_CSD;
    case OPENCHAOJI_GBT27930_A_PGN_CEM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CEM;

    case OPENCHAOJI_GBT27930_A_PGN_BHM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BHM;
    case OPENCHAOJI_GBT27930_A_PGN_BRM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BRM;
    case OPENCHAOJI_GBT27930_A_PGN_BCP: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCP;
    case OPENCHAOJI_GBT27930_A_PGN_BRO: return OPENCHAOJI_GBT27930_A_MSG_LEN_BRO;
    case OPENCHAOJI_GBT27930_A_PGN_BCL: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCL;
    case OPENCHAOJI_GBT27930_A_PGN_BCS: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCS;
    case OPENCHAOJI_GBT27930_A_PGN_BSM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSM;
    case OPENCHAOJI_GBT27930_A_PGN_BMV: return OPENCHAOJI_GBT27930_A_MSG_LEN_BMV_MIN;
    case OPENCHAOJI_GBT27930_A_PGN_BMT: return OPENCHAOJI_GBT27930_A_MSG_LEN_BMT_MIN;
    case OPENCHAOJI_GBT27930_A_PGN_BSP: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSP_MIN;
    case OPENCHAOJI_GBT27930_A_PGN_BST: return OPENCHAOJI_GBT27930_A_MSG_LEN_BST;
    case OPENCHAOJI_GBT27930_A_PGN_BSD: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSD;
    case OPENCHAOJI_GBT27930_A_PGN_BEM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BEM;
    default:
        return 0;
    }
}

/**
 * @function OpenChaoJi_gbt27930_a_msg_len_min_v1_0
 * @brief 获取消息最小长度 (协议版本号V1.0, 用于解码校验)
 * @param pgi 消息类型
 * @return int 消息最小长度
 */
extern int OpenChaoJi_gbt27930_a_msg_len_min_v1_0(uint8_t pgi)
{
    switch (pgi) {
    case OPENCHAOJI_GBT27930_A_PGN_CHM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CHM;
    case OPENCHAOJI_GBT27930_A_PGN_CRM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CRM;
    case OPENCHAOJI_GBT27930_A_PGN_CTS: return OPENCHAOJI_GBT27930_A_MSG_LEN_CTS;
    case OPENCHAOJI_GBT27930_A_PGN_CML: return OPENCHAOJI_GBT27930_A_MSG_LEN_CML_VER_1_0;
    case OPENCHAOJI_GBT27930_A_PGN_CRO: return OPENCHAOJI_GBT27930_A_MSG_LEN_CRO;
    case OPENCHAOJI_GBT27930_A_PGN_CCS: return OPENCHAOJI_GBT27930_A_MSG_LEN_CCS_VER_1_0;
    case OPENCHAOJI_GBT27930_A_PGN_CST: return OPENCHAOJI_GBT27930_A_MSG_LEN_CST;
    case OPENCHAOJI_GBT27930_A_PGN_CSD: return OPENCHAOJI_GBT27930_A_MSG_LEN_CSD;
    case OPENCHAOJI_GBT27930_A_PGN_CEM: return OPENCHAOJI_GBT27930_A_MSG_LEN_CEM;

    case OPENCHAOJI_GBT27930_A_PGN_BHM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BHM;
    case OPENCHAOJI_GBT27930_A_PGN_BRM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BRM_VER_1_0;
    case OPENCHAOJI_GBT27930_A_PGN_BCP: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCP;
    case OPENCHAOJI_GBT27930_A_PGN_BRO: return OPENCHAOJI_GBT27930_A_MSG_LEN_BRO;
    case OPENCHAOJI_GBT27930_A_PGN_BCL: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCL;
    case OPENCHAOJI_GBT27930_A_PGN_BCS: return OPENCHAOJI_GBT27930_A_MSG_LEN_BCS;
    case OPENCHAOJI_GBT27930_A_PGN_BSM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSM;
    case OPENCHAOJI_GBT27930_A_PGN_BMV: return OPENCHAOJI_GBT27930_A_MSG_LEN_BMV_MIN;
    case OPENCHAOJI_GBT27930_A_PGN_BMT: return OPENCHAOJI_GBT27930_A_MSG_LEN_BMT_MIN;
    case OPENCHAOJI_GBT27930_A_PGN_BSP: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSP_MIN;
    case OPENCHAOJI_GBT27930_A_PGN_BST: return OPENCHAOJI_GBT27930_A_MSG_LEN_BST;
    case OPENCHAOJI_GBT27930_A_PGN_BSD: return OPENCHAOJI_GBT27930_A_MSG_LEN_BSD;
    case OPENCHAOJI_GBT27930_A_PGN_BEM: return OPENCHAOJI_GBT27930_A_MSG_LEN_BEM;
    default:
        return 0;
    }
}

/**
 * 各类型PGI的编码
 */

static bool OpenChaoJi_gbt27930_a_msg_decode_chm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    bs_read_bytes(&bs, msg->msg.chm.pro_version, 3);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_crm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.crm.recognition_result = bs_read(&bs, 8);
    msg->msg.crm.charger_id = bs_read(&bs, 32);
    bs_read_bytes(&bs, msg->msg.crm.charger_location, 3);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_cts(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    bs_read_bytes(&bs, msg->msg.cts.time, 7);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_cml(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.cml.max_output_voltage = bs_read(&bs, 16);
    msg->msg.cml.min_output_voltage = bs_read(&bs, 16);
    msg->msg.cml.max_output_current = bs_read(&bs, 16);
    if (len == OPENCHAOJI_GBT27930_A_MSG_LEN_CML)
        msg->msg.cml.min_output_current = bs_read(&bs, 16);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_cro(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.cro.charger_ready_for_charging = bs_read(&bs, 8);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_ccs(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.ccs.output_voltage_value = bs_read(&bs, 16);
    msg->msg.ccs.output_current_value = bs_read(&bs, 16);
    msg->msg.ccs.cumulative_charging_time = bs_read(&bs, 16);
    if (len == OPENCHAOJI_GBT27930_A_MSG_LEN_CCS)
    {
        msg->msg.ccs.state.bits.charging_permissible = bs_read(&bs, 2);
        msg->msg.ccs.state.bits.res = bs_read(&bs, 6);
    }
    else
    {
        msg->msg.ccs.state.bits.charging_permissible = OPENCHAOJI_GBT27930_A_PAUSE_STATUS_CHARGE;
    }

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_cst(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.cst.stop_code.bits.condition_reached_suspends = bs_read(&bs, 2);
    msg->msg.cst.stop_code.bits.artificial_suspends = bs_read(&bs, 2);
    msg->msg.cst.stop_code.bits.fault_suspends = bs_read(&bs, 2);
    msg->msg.cst.stop_code.bits.bms_actively_suspends = bs_read(&bs, 2);
    msg->msg.cst.fault_code.bits.charger_over_temp = bs_read(&bs, 2);
    msg->msg.cst.fault_code.bits.charging_connector_fault = bs_read(&bs, 2);
    msg->msg.cst.fault_code.bits.charger_inner_part_over_temp = bs_read(&bs, 2);
    msg->msg.cst.fault_code.bits.can_not_supply_req_energy = bs_read(&bs, 2);
    msg->msg.cst.fault_code.bits.emergency_stop = bs_read(&bs, 2);
    msg->msg.cst.fault_code.bits.other_fault = bs_read(&bs, 2);
    msg->msg.cst.fault_code.bits.self_check_fault = bs_read(&bs, 2);
    msg->msg.cst.fault_code.bits.precharging_fault = bs_read(&bs, 2);
    msg->msg.cst.error_code.bits.current_mismatch_error = bs_read(&bs, 2);
    msg->msg.cst.error_code.bits.voltage_abnormal_error = bs_read(&bs, 2);
    msg->msg.cst.error_code.bits.param_mismatch_error = bs_read(&bs, 2);
    msg->msg.cst.error_code.bits.res = bs_read(&bs, 2);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_csd(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.csd.cumulative_charging_time = bs_read(&bs, 16);
    msg->msg.csd.output_energy = bs_read(&bs, 16);
    msg->msg.csd.charger_id = bs_read(&bs, 32);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_cem(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.cem.tout_code.bits.timeout_brm = bs_read(&bs, 2);
    msg->msg.cem.tout_code.bits.rev1 = bs_read(&bs, 6);
    msg->msg.cem.tout_code.bits.timeout_bcp = bs_read(&bs, 2);
    msg->msg.cem.tout_code.bits.timeout_bro = bs_read(&bs, 2);
    msg->msg.cem.tout_code.bits.rev2 = bs_read(&bs, 4);
    msg->msg.cem.tout_code.bits.timeout_bcs = bs_read(&bs, 2);
    msg->msg.cem.tout_code.bits.timeout_bcl = bs_read(&bs, 2);
    msg->msg.cem.tout_code.bits.timeout_bst = bs_read(&bs, 2);
    msg->msg.cem.tout_code.bits.rev3 = bs_read(&bs, 2);
    msg->msg.cem.tout_code.bits.timeout_bsd = bs_read(&bs, 2);
    msg->msg.cem.tout_code.bits.timeout_bsm = bs_read(&bs, 2);
    msg->msg.cem.tout_code.bits.rev4 = bs_read(&bs, 4);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bhm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.bhm.insul_request_voltage = bs_read(&bs, 16);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_brm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    bs_read_bytes(&bs, msg->msg.brm.pro_version, 3);
    msg->msg.brm.batt_type = bs_read(&bs, 8);
    msg->msg.brm.rated_capacity = bs_read(&bs, 16);
    msg->msg.brm.rated_voltage = bs_read(&bs, 16);
    bs_read_bytes(&bs, msg->msg.brm.batt_factory, 4);
    bs_read_bytes(&bs, msg->msg.brm.batt_sn, 4);
    msg->msg.brm.batt_date_year = bs_read(&bs, 8);
    msg->msg.brm.batt_date_month = bs_read(&bs, 8);
    msg->msg.brm.batt_date_day = bs_read(&bs, 8);
    bs_read_bytes(&bs, msg->msg.brm.charge_cycles, 3);
    msg->msg.brm.batt_property = bs_read(&bs, 8);
    msg->msg.brm.res = bs_read(&bs, 8);
    bs_read_bytes(&bs, msg->msg.brm.evin, 17);
    if (len == OPENCHAOJI_GBT27930_A_MSG_LEN_BRM)
        bs_read_bytes(&bs, msg->msg.brm.sw_version, 8);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bcp(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.bcp.allow_cellvolt = bs_read(&bs, 16);
    msg->msg.bcp.allow_current = bs_read(&bs, 16);
    msg->msg.bcp.rated_energy = bs_read(&bs, 16);
    msg->msg.bcp.allow_voltage = bs_read(&bs, 16);
    msg->msg.bcp.allow_tempera = bs_read(&bs, 8);
    msg->msg.bcp.batt_soc = bs_read(&bs, 16);
    msg->msg.bcp.measured_voltage = bs_read(&bs, 16);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bro(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.bro.bms_ready = bs_read(&bs, 8);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bcl(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.bcl.target_voltage = bs_read(&bs, 16);
    msg->msg.bcl.target_current = bs_read(&bs, 16);
    msg->msg.bcl.charge_mode = bs_read(&bs, 8);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bcs(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.bcs.measured_voltage = bs_read(&bs, 16);
    msg->msg.bcs.measured_current = bs_read(&bs, 16);
    msg->msg.bcs.max_cellvolt.bits.value = bs_read(&bs, 12);
    msg->msg.bcs.max_cellvolt.bits.group = bs_read(&bs, 4);
    msg->msg.bcs.soc = bs_read(&bs, 8);
    msg->msg.bcs.expected_time = bs_read(&bs, 16);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bsm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.bsm.max_cellvolt_id = bs_read(&bs, 8);
    msg->msg.bsm.max_tempera = bs_read(&bs, 8);
    msg->msg.bsm.max_tempera_id = bs_read(&bs, 8);
    msg->msg.bsm.min_tempera = bs_read(&bs, 8);
    msg->msg.bsm.min_tempera_id = bs_read(&bs, 8);
    msg->msg.bsm.batt_state.bits.warn_cellvolt = bs_read(&bs, 2);
    msg->msg.bsm.batt_state.bits.warn_soc = bs_read(&bs, 2);
    msg->msg.bsm.batt_state.bits.warn_current = bs_read(&bs, 2);
    msg->msg.bsm.batt_state.bits.warn_tempera = bs_read(&bs, 2);
    msg->msg.bsm.batt_state.bits.warn_insul = bs_read(&bs, 2);
    msg->msg.bsm.batt_state.bits.warn_connector = bs_read(&bs, 2);
    msg->msg.bsm.batt_state.bits.charge_enable = bs_read(&bs, 2);
    msg->msg.bsm.batt_state.bits.res = bs_read(&bs, 2);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bmv(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    if (len > OPENCHAOJI_GBT27930_A_MSG_LEN_BMV)
        len = OPENCHAOJI_GBT27930_A_MSG_LEN_BMV;
    bs_init(&bs, data, len);

    msg->msg.bmv.cellvolt_num = len / 2;
    for (int i = 0; i < msg->msg.bmv.cellvolt_num; i++)
    {
        msg->msg.bmv.cellvolt[i].bits.value = bs_read(&bs, 12);
        msg->msg.bmv.cellvolt[i].bits.group = bs_read(&bs, 4);
    }

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bmt(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    if (len > OPENCHAOJI_GBT27930_A_MSG_LEN_BMT)
        len = OPENCHAOJI_GBT27930_A_MSG_LEN_BMT;
    bs_init(&bs, data, len);

    msg->msg.bmt.tempera_num = len;
    bs_read_bytes(&bs, msg->msg.bmt.tempera, msg->msg.bmt.tempera_num);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bsp(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    if (len > OPENCHAOJI_GBT27930_A_MSG_LEN_BSP)
        len = OPENCHAOJI_GBT27930_A_MSG_LEN_BSP;
    bs_init(&bs, data, len);

    msg->msg.bsp.res_num = len;
    bs_read_bytes(&bs, msg->msg.bsp.res, msg->msg.bsp.res_num);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bst(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.bst.stop_code.bits.soc = bs_read(&bs, 2);
    msg->msg.bst.stop_code.bits.voltage = bs_read(&bs, 2);
    msg->msg.bst.stop_code.bits.cellvolt = bs_read(&bs, 2);
    msg->msg.bst.stop_code.bits.charger = bs_read(&bs, 2);

    msg->msg.bst.fault_code.bits.insul = bs_read(&bs, 2);
    msg->msg.bst.fault_code.bits.inlet_tempera = bs_read(&bs, 2);
    msg->msg.bst.fault_code.bits.cable_tempera = bs_read(&bs, 2);
    msg->msg.bst.fault_code.bits.coupler = bs_read(&bs, 2);
    msg->msg.bst.fault_code.bits.batt_tempera = bs_read(&bs, 2);
    msg->msg.bst.fault_code.bits.relay = bs_read(&bs, 2);
    msg->msg.bst.fault_code.bits.cc2_volt = bs_read(&bs, 2);
    msg->msg.bst.fault_code.bits.other = bs_read(&bs, 2);

    msg->msg.bst.error_code.bits.current = bs_read(&bs, 2);
    msg->msg.bst.error_code.bits.voltage = bs_read(&bs, 2);
    msg->msg.bst.error_code.bits.param = bs_read(&bs, 2);
    msg->msg.bst.error_code.bits.res = bs_read(&bs, 2);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bsd(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.bsd.end_soc = bs_read(&bs, 8);
    msg->msg.bsd.min_cellvolt = bs_read(&bs, 16);
    msg->msg.bsd.max_cellvolt = bs_read(&bs, 16);
    msg->msg.bsd.min_tempera = bs_read(&bs, 8);
    msg->msg.bsd.max_tempera = bs_read(&bs, 8);

    return true;
}

static bool OpenChaoJi_gbt27930_a_msg_decode_bem(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int len)
{
    bs_t bs;
    bs_init(&bs, data, len);

    msg->msg.bem.tout_code.bits.crm_00 = bs_read(&bs, 2);
    msg->msg.bem.tout_code.bits.crm_aa = bs_read(&bs, 2);
    msg->msg.bem.tout_code.bits.res1 = bs_read(&bs, 4);
    msg->msg.bem.tout_code.bits.cml = bs_read(&bs, 2);
    msg->msg.bem.tout_code.bits.cro = bs_read(&bs, 2);
    msg->msg.bem.tout_code.bits.res2 = bs_read(&bs, 4);
    msg->msg.bem.tout_code.bits.ccs = bs_read(&bs, 2);
    msg->msg.bem.tout_code.bits.cst = bs_read(&bs, 2);
    msg->msg.bem.tout_code.bits.res3 = bs_read(&bs, 4);
    msg->msg.bem.tout_code.bits.csd = bs_read(&bs, 2);
    msg->msg.bem.tout_code.bits.res4 = bs_read(&bs, 6);

    return true;
}

/**
 * @function OpenChaoJi_gbt27930_a_msg_decode
 * @brief 解码
 * @param msg 消息结构体(输出)
 * @param data 数据(输入)
 * @param len 数据长度
 * @return true 成功
 */
bool OpenChaoJi_gbt27930_a_msg_decode(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char pf, unsigned char *data, int len, int ver)
{
    if (msg == NULL || data == NULL) {
        LOG_CRIT("msg or data is NULL");
        return false;
    }

    if (len < 1) {
        LOG_ERR("gbt_a data_len[%d] < 1", len);
        return false;
    }

    int pgi_len = OpenChaoJi_gbt27930_a_msg_len_min(pf);
    if (ver == OPENCHAOJI_GBT27930_A_PROTOCOL_VERSION_TYPE_MAKE(1,0,0))
        pgi_len = OpenChaoJi_gbt27930_a_msg_len_min_v1_0(pf);

    if (len < pgi_len) {
        LOG_ERR("gbt_a data_len[%d] < pgi_len[%d]", len, pgi_len);
        return false;
    }

    msg->pid = pf;

    switch (pf) {
    case OPENCHAOJI_GBT27930_A_PGN_CHM: return OpenChaoJi_gbt27930_a_msg_decode_chm(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_CRM: return OpenChaoJi_gbt27930_a_msg_decode_crm(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_CTS: return OpenChaoJi_gbt27930_a_msg_decode_cts(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_CML: return OpenChaoJi_gbt27930_a_msg_decode_cml(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_CRO: return OpenChaoJi_gbt27930_a_msg_decode_cro(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_CCS: return OpenChaoJi_gbt27930_a_msg_decode_ccs(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_CST: return OpenChaoJi_gbt27930_a_msg_decode_cst(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_CSD: return OpenChaoJi_gbt27930_a_msg_decode_csd(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_CEM: return OpenChaoJi_gbt27930_a_msg_decode_cem(msg, data, pgi_len);

    case OPENCHAOJI_GBT27930_A_PGN_BHM: return OpenChaoJi_gbt27930_a_msg_decode_bhm(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_BRM: return OpenChaoJi_gbt27930_a_msg_decode_brm(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_BCP: return OpenChaoJi_gbt27930_a_msg_decode_bcp(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_BRO: return OpenChaoJi_gbt27930_a_msg_decode_bro(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_BCL: return OpenChaoJi_gbt27930_a_msg_decode_bcl(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_BCS: return OpenChaoJi_gbt27930_a_msg_decode_bcs(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_BSM: return OpenChaoJi_gbt27930_a_msg_decode_bsm(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_BMV: return OpenChaoJi_gbt27930_a_msg_decode_bmv(msg, data, len); // 不定长
    case OPENCHAOJI_GBT27930_A_PGN_BMT: return OpenChaoJi_gbt27930_a_msg_decode_bmt(msg, data, len); // 不定长
    case OPENCHAOJI_GBT27930_A_PGN_BSP: return OpenChaoJi_gbt27930_a_msg_decode_bsp(msg, data, len); // 不定长
    case OPENCHAOJI_GBT27930_A_PGN_BST: return OpenChaoJi_gbt27930_a_msg_decode_bst(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_BSD: return OpenChaoJi_gbt27930_a_msg_decode_bsd(msg, data, pgi_len);
    case OPENCHAOJI_GBT27930_A_PGN_BEM: return OpenChaoJi_gbt27930_a_msg_decode_bem(msg, data, pgi_len);
    default:
        return false;
    }
}


/*********************************************************************************************************************************************/

/**
 * 各类型PGI消息编码
 */

static void OpenChaoJi_gbt27930_a_msg_encode_chm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write_bytes(&bs, msg->msg.chm.pro_version, 3);
}

static void OpenChaoJi_gbt27930_a_msg_encode_crm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.crm.recognition_result, 8);
    bs_write(&bs, msg->msg.crm.charger_id, 32);
    bs_write_bytes(&bs, msg->msg.crm.charger_location, 3);
}

static void OpenChaoJi_gbt27930_a_msg_encode_cts(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write_bytes(&bs, msg->msg.cts.time, 7);
}

static void OpenChaoJi_gbt27930_a_msg_encode_cml(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.cml.max_output_voltage, 16);
    bs_write(&bs, msg->msg.cml.min_output_voltage, 16);
    bs_write(&bs, msg->msg.cml.max_output_current, 16);
    bs_write(&bs, msg->msg.cml.min_output_current, 16);
}

static void OpenChaoJi_gbt27930_a_msg_encode_cro(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.cro.charger_ready_for_charging, 8);
}

static void OpenChaoJi_gbt27930_a_msg_encode_ccs(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.ccs.output_voltage_value, 16);
    bs_write(&bs, msg->msg.ccs.output_current_value, 16);
    bs_write(&bs, msg->msg.ccs.cumulative_charging_time, 16);
    bs_write(&bs, msg->msg.ccs.state.bits.charging_permissible, 2);
    bs_write(&bs, msg->msg.ccs.state.bits.res, 6);
}

static void OpenChaoJi_gbt27930_a_msg_encode_cst(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.cst.stop_code.bits.condition_reached_suspends, 2);
    bs_write(&bs, msg->msg.cst.stop_code.bits.artificial_suspends, 2);
    bs_write(&bs, msg->msg.cst.stop_code.bits.fault_suspends, 2);
    bs_write(&bs, msg->msg.cst.stop_code.bits.bms_actively_suspends, 2);
    bs_write(&bs, msg->msg.cst.fault_code.bits.charger_over_temp, 2);
    bs_write(&bs, msg->msg.cst.fault_code.bits.charging_connector_fault, 2);
    bs_write(&bs, msg->msg.cst.fault_code.bits.charger_inner_part_over_temp, 2);
    bs_write(&bs, msg->msg.cst.fault_code.bits.can_not_supply_req_energy, 2);
    bs_write(&bs, msg->msg.cst.fault_code.bits.emergency_stop, 2);
    bs_write(&bs, msg->msg.cst.fault_code.bits.other_fault, 2);
    bs_write(&bs, msg->msg.cst.fault_code.bits.self_check_fault, 2);
    bs_write(&bs, msg->msg.cst.fault_code.bits.precharging_fault, 2);
    bs_write(&bs, msg->msg.cst.error_code.bits.current_mismatch_error, 2);
    bs_write(&bs, msg->msg.cst.error_code.bits.voltage_abnormal_error, 2);
    bs_write(&bs, msg->msg.cst.error_code.bits.param_mismatch_error, 2);
    bs_write(&bs, msg->msg.cst.error_code.bits.res, 2);
}

static void OpenChaoJi_gbt27930_a_msg_encode_csd(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.csd.cumulative_charging_time, 16);
    bs_write(&bs, msg->msg.csd.output_energy, 16);
    bs_write(&bs, msg->msg.csd.charger_id, 32);
}

static void OpenChaoJi_gbt27930_a_msg_encode_cem(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.cem.tout_code.bits.timeout_brm, 2);
    bs_write(&bs, msg->msg.cem.tout_code.bits.rev1, 6);
    bs_write(&bs, msg->msg.cem.tout_code.bits.timeout_bcp, 2);
    bs_write(&bs, msg->msg.cem.tout_code.bits.timeout_bro, 2);
    bs_write(&bs, msg->msg.cem.tout_code.bits.rev2, 4);
    bs_write(&bs, msg->msg.cem.tout_code.bits.timeout_bcs, 2);
    bs_write(&bs, msg->msg.cem.tout_code.bits.timeout_bcl, 2);
    bs_write(&bs, msg->msg.cem.tout_code.bits.timeout_bst, 2);
    bs_write(&bs, msg->msg.cem.tout_code.bits.rev3, 2);
    bs_write(&bs, msg->msg.cem.tout_code.bits.timeout_bsd, 2);
    bs_write(&bs, msg->msg.cem.tout_code.bits.timeout_bsm, 2);
    bs_write(&bs, msg->msg.cem.tout_code.bits.rev4, 4);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bhm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.bhm.insul_request_voltage, 16);
}

static void OpenChaoJi_gbt27930_a_msg_encode_brm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write_bytes(&bs, msg->msg.brm.pro_version, 3);
    bs_write(&bs, msg->msg.brm.batt_type, 8);
    bs_write(&bs, msg->msg.brm.rated_capacity, 16);
    bs_write(&bs, msg->msg.brm.rated_voltage, 16);
    bs_write_bytes(&bs, msg->msg.brm.batt_factory, 4);
    bs_write_bytes(&bs, msg->msg.brm.batt_sn, 4);
    bs_write(&bs, msg->msg.brm.batt_date_year, 8);
    bs_write(&bs, msg->msg.brm.batt_date_month, 8);
    bs_write(&bs, msg->msg.brm.batt_date_day, 8);
    bs_write_bytes(&bs, msg->msg.brm.charge_cycles, 3);
    bs_write(&bs, msg->msg.brm.batt_property, 8);
    bs_write(&bs, msg->msg.brm.res, 8);
    bs_write_bytes(&bs, msg->msg.brm.evin, 17);
    bs_write_bytes(&bs, msg->msg.brm.sw_version, 8);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bcp(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.bcp.allow_cellvolt, 16);
    bs_write(&bs, msg->msg.bcp.allow_current, 16);
    bs_write(&bs, msg->msg.bcp.rated_energy, 16);
    bs_write(&bs, msg->msg.bcp.allow_voltage, 16);
    bs_write(&bs, msg->msg.bcp.allow_tempera, 8);
    bs_write(&bs, msg->msg.bcp.batt_soc, 16);
    bs_write(&bs, msg->msg.bcp.measured_voltage, 16);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bro(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.bro.bms_ready, 8);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bcl(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.bcl.target_voltage, 16);
    bs_write(&bs, msg->msg.bcl.target_current, 16);
    bs_write(&bs, msg->msg.bcl.charge_mode, 8);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bcs(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.bcs.measured_voltage, 16);
    bs_write(&bs, msg->msg.bcs.measured_current, 16);
    bs_write(&bs, msg->msg.bcs.max_cellvolt.bits.value, 12);
    bs_write(&bs, msg->msg.bcs.max_cellvolt.bits.group, 4);
    bs_write(&bs, msg->msg.bcs.soc, 8);
    bs_write(&bs, msg->msg.bcs.expected_time, 16);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bsm(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.bsm.max_cellvolt_id, 8);
    bs_write(&bs, msg->msg.bsm.max_tempera, 8);
    bs_write(&bs, msg->msg.bsm.max_tempera_id, 8);
    bs_write(&bs, msg->msg.bsm.min_tempera, 8);
    bs_write(&bs, msg->msg.bsm.min_tempera_id, 8);
    bs_write(&bs, msg->msg.bsm.batt_state.bits.warn_cellvolt, 2);
    bs_write(&bs, msg->msg.bsm.batt_state.bits.warn_soc, 2);
    bs_write(&bs, msg->msg.bsm.batt_state.bits.warn_current, 2);
    bs_write(&bs, msg->msg.bsm.batt_state.bits.warn_tempera, 2);
    bs_write(&bs, msg->msg.bsm.batt_state.bits.warn_insul, 2);
    bs_write(&bs, msg->msg.bsm.batt_state.bits.warn_connector, 2);
    bs_write(&bs, msg->msg.bsm.batt_state.bits.charge_enable, 2);
    bs_write(&bs, msg->msg.bsm.batt_state.bits.res, 2);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bmv(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);
    for (int i = 0; i < msg->msg.bmv.cellvolt_num; i++)
    {
        bs_write(&bs, msg->msg.bmv.cellvolt[i].bits.value, 12);
        bs_write(&bs, msg->msg.bmv.cellvolt[i].bits.group, 4);
    }
}

static void OpenChaoJi_gbt27930_a_msg_encode_bmt(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);
    bs_write_bytes(&bs, msg->msg.bmt.tempera, msg->msg.bmt.tempera_num);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bsp(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);
    bs_write_bytes(&bs, msg->msg.bsp.res, msg->msg.bsp.res_num);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bst(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.bst.stop_code.bits.soc, 2);
    bs_write(&bs, msg->msg.bst.stop_code.bits.voltage, 2);
    bs_write(&bs, msg->msg.bst.stop_code.bits.cellvolt, 2);
    bs_write(&bs, msg->msg.bst.stop_code.bits.charger, 2);

    bs_write(&bs, msg->msg.bst.fault_code.bits.insul, 2);
    bs_write(&bs, msg->msg.bst.fault_code.bits.inlet_tempera, 2);
    bs_write(&bs, msg->msg.bst.fault_code.bits.cable_tempera, 2);
    bs_write(&bs, msg->msg.bst.fault_code.bits.coupler, 2);
    bs_write(&bs, msg->msg.bst.fault_code.bits.batt_tempera, 2);
    bs_write(&bs, msg->msg.bst.fault_code.bits.relay, 2);
    bs_write(&bs, msg->msg.bst.fault_code.bits.cc2_volt, 2);
    bs_write(&bs, msg->msg.bst.fault_code.bits.other, 2);

    bs_write(&bs, msg->msg.bst.error_code.bits.current, 2);
    bs_write(&bs, msg->msg.bst.error_code.bits.voltage, 2);
    bs_write(&bs, msg->msg.bst.error_code.bits.param, 2);
    bs_write(&bs, msg->msg.bst.error_code.bits.res, 2);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bsd(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.bsd.end_soc, 8);
    bs_write(&bs, msg->msg.bsd.min_cellvolt, 16);
    bs_write(&bs, msg->msg.bsd.max_cellvolt, 16);
    bs_write(&bs, msg->msg.bsd.min_tempera, 8);
    bs_write(&bs, msg->msg.bsd.max_tempera, 8);
}

static void OpenChaoJi_gbt27930_a_msg_encode_bem(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    bs_t bs;
    bs_init(&bs, data, max_len);

    bs_write(&bs, msg->msg.bem.tout_code.bits.crm_00, 2);
    bs_write(&bs, msg->msg.bem.tout_code.bits.crm_aa, 2);
    bs_write(&bs, msg->msg.bem.tout_code.bits.res1, 4);
    bs_write(&bs, msg->msg.bem.tout_code.bits.cml, 2);
    bs_write(&bs, msg->msg.bem.tout_code.bits.cro, 2);
    bs_write(&bs, msg->msg.bem.tout_code.bits.res2, 4);
    bs_write(&bs, msg->msg.bem.tout_code.bits.ccs, 2);
    bs_write(&bs, msg->msg.bem.tout_code.bits.cst, 2);
    bs_write(&bs, msg->msg.bem.tout_code.bits.res3, 4);
    bs_write(&bs, msg->msg.bem.tout_code.bits.csd, 2);
    bs_write(&bs, msg->msg.bem.tout_code.bits.res4, 6);
}


/**
 * @function OpenChaoJi_gbt27930_a_msg_encode
 * @brief 编码
 * @param msg 消息结构体(输入)
 * @param data 数据(输出)
 * @param max_len 数据最大长度
 * @return int 实际编码数据长度, 小于0表示失败
 */
int OpenChaoJi_gbt27930_a_msg_encode(struct OpenChaoJi_gbt27930_a_msg *msg, unsigned char *data, int max_len)
{
    if (msg == NULL || data == NULL) {
        LOG_CRIT("msg or data is NULL");
        return 0;
    }

    int pgi_len = OpenChaoJi_gbt27930_a_msg_len(msg);

    if (max_len < pgi_len) {
        LOG_ERR("gbt_a max_len[%d] < pgi_len[%d]", max_len, pgi_len);
        return false;
    }

    switch (msg->pid) {
    case OPENCHAOJI_GBT27930_A_PGN_CHM: OpenChaoJi_gbt27930_a_msg_encode_chm(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_CRM: OpenChaoJi_gbt27930_a_msg_encode_crm(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_CTS: OpenChaoJi_gbt27930_a_msg_encode_cts(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_CML: OpenChaoJi_gbt27930_a_msg_encode_cml(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_CRO: OpenChaoJi_gbt27930_a_msg_encode_cro(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_CCS: OpenChaoJi_gbt27930_a_msg_encode_ccs(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_CST: OpenChaoJi_gbt27930_a_msg_encode_cst(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_CSD: OpenChaoJi_gbt27930_a_msg_encode_csd(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_CEM: OpenChaoJi_gbt27930_a_msg_encode_cem(msg, data, pgi_len); break;

    case OPENCHAOJI_GBT27930_A_PGN_BHM: OpenChaoJi_gbt27930_a_msg_encode_bhm(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BRM: OpenChaoJi_gbt27930_a_msg_encode_brm(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BCP: OpenChaoJi_gbt27930_a_msg_encode_bcp(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BRO: OpenChaoJi_gbt27930_a_msg_encode_bro(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BCL: OpenChaoJi_gbt27930_a_msg_encode_bcl(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BCS: OpenChaoJi_gbt27930_a_msg_encode_bcs(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BSM: OpenChaoJi_gbt27930_a_msg_encode_bsm(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BMV: OpenChaoJi_gbt27930_a_msg_encode_bmv(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BMT: OpenChaoJi_gbt27930_a_msg_encode_bmt(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BSP: OpenChaoJi_gbt27930_a_msg_encode_bsp(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BST: OpenChaoJi_gbt27930_a_msg_encode_bst(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BSD: OpenChaoJi_gbt27930_a_msg_encode_bsd(msg, data, pgi_len); break;
    case OPENCHAOJI_GBT27930_A_PGN_BEM: OpenChaoJi_gbt27930_a_msg_encode_bem(msg, data, pgi_len); break;
    default:
        return 0;
    }

    return pgi_len;
}


/**
 * @function OpenChaoJi_gbt27930_a_msg_encode_data
 * @brief 编码, 并动态分配内存
 * @param msg 消息结构体(输入)
 * @param data_len 数据长度(输出)
 * @return unsigned char * 编码数据 NULL表示失败
 */
unsigned char * OpenChaoJi_gbt27930_a_msg_encode_data(struct OpenChaoJi_gbt27930_a_msg *msg, int * data_len)
{
    if (msg == NULL || data_len == NULL)
    {
        return NULL;
    }

    unsigned char *data = NULL;
    int max_len = OpenChaoJi_gbt27930_a_msg_len_max(msg->pid);
    data = (unsigned char *)OpenChaoJi_os_malloc(max_len);
    if (data == NULL)
    {
        return NULL;
    }

    int dst_len = OpenChaoJi_gbt27930_a_msg_encode(msg, data, max_len);
    if (dst_len <= 0)
    {
        OpenChaoJi_os_free(data);
        return NULL;
    }

    *data_len = dst_len;
    return data;
}

/*********************************************************************************************************************************************/
#define GBT27930_A_MSG_LOG LOG_NOTICE

/**
 * 各类型PGI日志
 */
static void OpenChaoJi_gbt27930_a_msg_log_chm(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    char tmp[101]={0};

    GBT27930_A_MSG_LOG("msg_chm");
    snprintf(tmp, 100, "\t pro_version=[%02x %02x %02x]", msg->msg.chm.pro_version[0] \
                                                        , msg->msg.chm.pro_version[1] \
                                                        , msg->msg.chm.pro_version[2]);
    GBT27930_A_MSG_LOG("%s", tmp);
}

static void OpenChaoJi_gbt27930_a_msg_log_crm(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_crm");
    GBT27930_A_MSG_LOG("\t recognition_result=%s", enum_names_OpenChaoJi_gbt27930_a_RecognizeType(msg->msg.crm.recognition_result));
    GBT27930_A_MSG_LOG("\t charger_id=%d", msg->msg.crm.charger_id);

    char location[5]={0};
    memcpy(location, msg->msg.crm.charger_location, 3);
    GBT27930_A_MSG_LOG("\t charger_location=%s", location);
}

static void OpenChaoJi_gbt27930_a_msg_log_cts(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    char tmp[101]={0};

    GBT27930_A_MSG_LOG("msg_cts");
    snprintf(tmp, 100, "\t time=%02x%02x-%02x-%02x %02x:%02x:%02x", msg->msg.cts.time[5] \
                                                                  , msg->msg.cts.time[6] \
                                                                  , msg->msg.cts.time[4] \
                                                                  , msg->msg.cts.time[3] \
                                                                  , msg->msg.cts.time[2] \
                                                                  , msg->msg.cts.time[1] \
                                                                  , msg->msg.cts.time[0]);
    GBT27930_A_MSG_LOG("%s", tmp);
}

static void OpenChaoJi_gbt27930_a_msg_log_cml(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_cml");
    GBT27930_A_MSG_LOG("\t max_output_voltage=%d(0.1V)", msg->msg.cml.max_output_voltage);
    GBT27930_A_MSG_LOG("\t min_output_voltage=%d(0.1V)", msg->msg.cml.min_output_voltage);
    GBT27930_A_MSG_LOG("\t max_output_current=%d(0.1A)", (int)msg->msg.cml.max_output_current-4000);
    GBT27930_A_MSG_LOG("\t min_output_current=%d(0.1A)", (int)msg->msg.cml.min_output_current-4000);
}

static void OpenChaoJi_gbt27930_a_msg_log_cro(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_cro");
    GBT27930_A_MSG_LOG("\t secc_ready=%s", enum_names_OpenChaoJi_gbt27930_a_ReadyType(msg->msg.cro.charger_ready_for_charging));
}

static void OpenChaoJi_gbt27930_a_msg_log_ccs(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_ccs");
    GBT27930_A_MSG_LOG("\t output_voltage_value=%d(0.1V)", msg->msg.ccs.output_voltage_value);
    GBT27930_A_MSG_LOG("\t output_current_value=%d(0.1A)", (int)msg->msg.ccs.output_current_value-4000);
    GBT27930_A_MSG_LOG("\t cumulative_charging_time=%d(1min)", msg->msg.ccs.cumulative_charging_time);
    GBT27930_A_MSG_LOG("\t charging_permissible=%s", enum_names_OpenChaoJi_gbt27930_a_PauseStatusType(msg->msg.ccs.state.bits.charging_permissible));
}

static void OpenChaoJi_gbt27930_a_msg_log_cst(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_cst");

    // GBT27930_A_MSG_LOG("\t stop_code=[0x%02x]",msg->msg.cst.stop_code.all);
    GBT27930_A_MSG_LOG("\t stop_code_condition_reached=%s", enum_names_OpenChaoJi_gbt27930_a_StopCodeState(msg->msg.cst.stop_code.bits.condition_reached_suspends));
    GBT27930_A_MSG_LOG("\t stop_code_artificial=%s", enum_names_OpenChaoJi_gbt27930_a_StopCodeState(msg->msg.cst.stop_code.bits.artificial_suspends));
    GBT27930_A_MSG_LOG("\t stop_code_fault_suspends=%s", enum_names_OpenChaoJi_gbt27930_a_StopCodeState(msg->msg.cst.stop_code.bits.fault_suspends));
    GBT27930_A_MSG_LOG("\t stop_code_bst=%s", enum_names_OpenChaoJi_gbt27930_a_StopCodeState(msg->msg.cst.stop_code.bits.bms_actively_suspends));
    GBT27930_A_MSG_LOG("\t ");

    // GBT27930_A_MSG_LOG("\t fault_code=[0x%04x]",msg->msg.cst.fault_code.all);
    GBT27930_A_MSG_LOG("\t fault_code_charger_over_temp=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.fault_code.bits.charger_over_temp));
    GBT27930_A_MSG_LOG("\t fault_code_charging_connector_fault=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.fault_code.bits.charging_connector_fault));
    GBT27930_A_MSG_LOG("\t fault_code_charger_inner_part_over_temp=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.fault_code.bits.charger_inner_part_over_temp));
    GBT27930_A_MSG_LOG("\t fault_code_can_not_supply_req_energy=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.fault_code.bits.can_not_supply_req_energy));
    GBT27930_A_MSG_LOG("\t fault_code_emergency_stop=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.fault_code.bits.emergency_stop));
    GBT27930_A_MSG_LOG("\t fault_code_other_fault=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.fault_code.bits.other_fault));
    GBT27930_A_MSG_LOG("\t fault_code_self_check_fault=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.fault_code.bits.self_check_fault));
    GBT27930_A_MSG_LOG("\t fault_code_precharging_fault=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.fault_code.bits.precharging_fault));
    GBT27930_A_MSG_LOG("\t ");

    // GBT27930_A_MSG_LOG("\t error_code=[0x%02x]",msg->msg.cst.error_code.all);
    GBT27930_A_MSG_LOG("\t error_code_current_mismatch_error=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.error_code.bits.current_mismatch_error));
    GBT27930_A_MSG_LOG("\t error_code_voltage_abnormal_error=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.error_code.bits.voltage_abnormal_error));
    GBT27930_A_MSG_LOG("\t error_code_param_mismatch_error=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.cst.error_code.bits.param_mismatch_error));
}

static void OpenChaoJi_gbt27930_a_msg_log_csd(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_csd");
    GBT27930_A_MSG_LOG("\t charging_time=%d(1min)", msg->msg.csd.cumulative_charging_time);
    GBT27930_A_MSG_LOG("\t output_energy=%d(0.1kWh)", msg->msg.csd.output_energy);
    GBT27930_A_MSG_LOG("\t charger_id=%d", msg->msg.csd.charger_id);
}

static void OpenChaoJi_gbt27930_a_msg_log_cem(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_cem");
    // GBT27930_A_MSG_LOG("\t tout_code=[0x%08x]", msg->msg.cem.tout_code.all);
    GBT27930_A_MSG_LOG("\t timeout_brm=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.cem.tout_code.bits.timeout_brm));
    GBT27930_A_MSG_LOG("\t timeout_bcp=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.cem.tout_code.bits.timeout_bcp));
    GBT27930_A_MSG_LOG("\t timeout_bro=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.cem.tout_code.bits.timeout_bro));
    GBT27930_A_MSG_LOG("\t timeout_bcs=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.cem.tout_code.bits.timeout_bcs));
    GBT27930_A_MSG_LOG("\t timeout_bcl=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.cem.tout_code.bits.timeout_bcl));
    GBT27930_A_MSG_LOG("\t timeout_bst=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.cem.tout_code.bits.timeout_bst));
    GBT27930_A_MSG_LOG("\t timeout_bsd=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.cem.tout_code.bits.timeout_bsd));
    GBT27930_A_MSG_LOG("\t timeout_bsm=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.cem.tout_code.bits.timeout_bsm));
}

static void OpenChaoJi_gbt27930_a_msg_log_bhm(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bhm");
    GBT27930_A_MSG_LOG("\t insul_request_voltage=%d(0.1V)", msg->msg.bhm.insul_request_voltage);
}

static void OpenChaoJi_gbt27930_a_msg_log_brm(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    char tmp[101]={0};

    GBT27930_A_MSG_LOG("msg_brm");
    snprintf(tmp, 100, "\t pro_version=[%02x %02x %02x]", msg->msg.brm.pro_version[0] \
                                                        , msg->msg.brm.pro_version[1] \
                                                        , msg->msg.brm.pro_version[2]);
    GBT27930_A_MSG_LOG("%s", tmp);
    GBT27930_A_MSG_LOG("\t batt_type=%s", enum_names_OpenChaoJi_gbt27930_a_BattType(msg->msg.brm.batt_type));
    GBT27930_A_MSG_LOG("\t rated_capacity=%d(0.1Ah)", msg->msg.brm.rated_capacity);
    GBT27930_A_MSG_LOG("\t rated_voltage=%d(0.1V)", msg->msg.brm.rated_voltage);
    memset(tmp, 0, sizeof(tmp));
    memcpy(tmp, msg->msg.brm.batt_factory, 4);
    GBT27930_A_MSG_LOG("\t batt_factory=%s", tmp);
    memset(tmp, 0, sizeof(tmp));
    snprintf(tmp, 100, "\t batt_sn=[%02x %02x %02x %02x]", msg->msg.brm.batt_sn[0] \
                                                        , msg->msg.brm.batt_sn[1] \
                                                        , msg->msg.brm.batt_sn[2] \
                                                        , msg->msg.brm.batt_sn[3]);
    GBT27930_A_MSG_LOG("%s", tmp);
    GBT27930_A_MSG_LOG("\t batt_date_year=%d", (int)msg->msg.brm.batt_date_year+1985);
    GBT27930_A_MSG_LOG("\t batt_date_month=%d", msg->msg.brm.batt_date_month);
    GBT27930_A_MSG_LOG("\t batt_date_day=%d", msg->msg.brm.batt_date_day);
    int value = 0;
    value = msg->msg.brm.charge_cycles[2];
    value <<= 8;
    value += msg->msg.brm.charge_cycles[1];
    value <<= 8;
    value += msg->msg.brm.charge_cycles[0];
    GBT27930_A_MSG_LOG("\t charge_cycles=%d", value);
    GBT27930_A_MSG_LOG("\t batt_property=%s", enum_names_OpenChaoJi_gbt27930_a_BattPropertyType(msg->msg.brm.batt_property));
    memset(tmp, 0, sizeof(tmp));
    memcpy(tmp, msg->msg.brm.evin, 17);
    GBT27930_A_MSG_LOG("\t evin=%s", tmp);
    memset(tmp, 0, sizeof(tmp));
    snprintf(tmp, 100, "\t sw_version=[%02x %02x %02x %02x %02x %02x %02x %02x]", msg->msg.brm.sw_version[0], msg->msg.brm.sw_version[1] \
                                                                                , msg->msg.brm.sw_version[2], msg->msg.brm.sw_version[3] \
                                                                                , msg->msg.brm.sw_version[4], msg->msg.brm.sw_version[5] \
                                                                                , msg->msg.brm.sw_version[6], msg->msg.brm.sw_version[7]);
    GBT27930_A_MSG_LOG("%s", tmp);
}

static void OpenChaoJi_gbt27930_a_msg_log_bcp(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bcp");
    GBT27930_A_MSG_LOG("\t allow_cellvolt=%d(0.01V)", msg->msg.bcp.allow_cellvolt);
    GBT27930_A_MSG_LOG("\t allow_current=%d(0.1A)", (int)msg->msg.bcp.allow_current-4000);
    GBT27930_A_MSG_LOG("\t rated_energy=%d(0.1kWh)", msg->msg.bcp.rated_energy);
    GBT27930_A_MSG_LOG("\t allow_voltage=%d(0.1V)", msg->msg.bcp.allow_voltage);
    GBT27930_A_MSG_LOG("\t allow_tempera=%d(1°C)", (int)msg->msg.bcp.allow_tempera-50);
    GBT27930_A_MSG_LOG("\t batt_soc=%d(0.1%%)", msg->msg.bcp.batt_soc);
    GBT27930_A_MSG_LOG("\t measured_voltage=%d(0.1V)", msg->msg.bcp.measured_voltage);
}

static void OpenChaoJi_gbt27930_a_msg_log_bro(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bro");
    GBT27930_A_MSG_LOG("\t evcc_ready=%s", enum_names_OpenChaoJi_gbt27930_a_ReadyType(msg->msg.bro.bms_ready));
}

static void OpenChaoJi_gbt27930_a_msg_log_bcl(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bcl");
    GBT27930_A_MSG_LOG("\t target_voltage=%d(0.1V)", msg->msg.bcl.target_voltage);
    GBT27930_A_MSG_LOG("\t target_current=%d(0.1A)", (int)msg->msg.bcl.target_current-4000);
    GBT27930_A_MSG_LOG("\t charge_mode=%s", enum_names_OpenChaoJi_gbt27930_a_ChargeModeType(msg->msg.bcl.charge_mode));
}

static void OpenChaoJi_gbt27930_a_msg_log_bcs(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bcs");
    GBT27930_A_MSG_LOG("\t measured_voltage=%d(0.1V)", msg->msg.bcs.measured_voltage);
    GBT27930_A_MSG_LOG("\t measured_current=%d(0.1A)", (int)msg->msg.bcs.measured_current-4000);
    GBT27930_A_MSG_LOG("\t max_cellvolt_value=%d(0.01V)", msg->msg.bcs.max_cellvolt.bits.value);
    GBT27930_A_MSG_LOG("\t max_cellvolt_group=%d", msg->msg.bcs.max_cellvolt.bits.group);
    GBT27930_A_MSG_LOG("\t soc=%d(1%%)", msg->msg.bcs.soc);
    GBT27930_A_MSG_LOG("\t expected_time=%d(1min)", msg->msg.bcs.expected_time);
}

static void OpenChaoJi_gbt27930_a_msg_log_bsm(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bsm");
    GBT27930_A_MSG_LOG("\t max_cellvolt_id=%d", (int)msg->msg.bsm.max_cellvolt_id+1);
    GBT27930_A_MSG_LOG("\t max_tempera=%d(1°C)", (int)msg->msg.bsm.max_tempera-50);
    GBT27930_A_MSG_LOG("\t max_tempera_id=%d", (int)msg->msg.bsm.max_tempera_id+1);
    GBT27930_A_MSG_LOG("\t min_tempera=%d(1°C)", (int)msg->msg.bsm.min_tempera-50);
    GBT27930_A_MSG_LOG("\t min_tempera_id=%d", (int)msg->msg.bsm.min_tempera_id+1);

    // GBT27930_A_MSG_LOG("\t batt_state=[0x%04x]", msg->msg.bsm.batt_state.all);
    GBT27930_A_MSG_LOG("\t warn_cellvolt=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState_CellVolt(msg->msg.bsm.batt_state.bits.warn_cellvolt));
    GBT27930_A_MSG_LOG("\t warn_soc=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState_SOC(msg->msg.bsm.batt_state.bits.warn_soc));
    GBT27930_A_MSG_LOG("\t warn_current=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bsm.batt_state.bits.warn_current));
    GBT27930_A_MSG_LOG("\t warn_tempera=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bsm.batt_state.bits.warn_tempera));
    GBT27930_A_MSG_LOG("\t warn_insul=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bsm.batt_state.bits.warn_insul));
    GBT27930_A_MSG_LOG("\t warn_connector=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bsm.batt_state.bits.warn_connector));
    GBT27930_A_MSG_LOG("\t charging_permissible=%s", enum_names_OpenChaoJi_gbt27930_a_PauseStatusType(msg->msg.bsm.batt_state.bits.charge_enable));
}

static void OpenChaoJi_gbt27930_a_msg_log_bmv(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bmv");
    for (int i=0; i<msg->msg.bmv.cellvolt_num; i++)
    {
        GBT27930_A_MSG_LOG("\t cell[%d]_group=%d", i, msg->msg.bmv.cellvolt[i].bits.group);
        GBT27930_A_MSG_LOG("\t cell[%d]_volt=%d(0.01V)", i, msg->msg.bmv.cellvolt[i].bits.value);
    }
}

static void OpenChaoJi_gbt27930_a_msg_log_bmt(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bmt");
    for (int i=0; i<msg->msg.bmt.tempera_num; i++)
    {
        GBT27930_A_MSG_LOG("\t tempera[%d]=%d(1°C)", i, (int)msg->msg.bmt.tempera[i]-50);
    }
}

static void OpenChaoJi_gbt27930_a_msg_log_bsp(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bsp");
    // for (int i=0; i<msg->msg.bsp.res_num; i++)
    // {
    //     GBT27930_A_MSG_LOG("\t res[i]=%02x", (int)msg->msg.bsp.res[i]);
    // }
}

static void OpenChaoJi_gbt27930_a_msg_log_bst(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bst");

    // GBT27930_A_MSG_LOG("\t stop_code=[0x%02x]", msg->msg.bst.stop_code.all);
    GBT27930_A_MSG_LOG("\t stop_code_soc=%s", enum_names_OpenChaoJi_gbt27930_a_StopCodeState(msg->msg.bst.stop_code.bits.soc));
    GBT27930_A_MSG_LOG("\t stop_code_voltage=%s", enum_names_OpenChaoJi_gbt27930_a_StopCodeState(msg->msg.bst.stop_code.bits.voltage));
    GBT27930_A_MSG_LOG("\t stop_code_cellvolt=%s", enum_names_OpenChaoJi_gbt27930_a_StopCodeState(msg->msg.bst.stop_code.bits.cellvolt));
    GBT27930_A_MSG_LOG("\t stop_code_charger=%s", enum_names_OpenChaoJi_gbt27930_a_StopCodeState(msg->msg.bst.stop_code.bits.charger));
    GBT27930_A_MSG_LOG("\t ");

    // GBT27930_A_MSG_LOG("\t fault_code=[0x%04x]", msg->msg.bst.fault_code.all);
    GBT27930_A_MSG_LOG("\t fault_code_insul=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.fault_code.bits.insul));
    GBT27930_A_MSG_LOG("\t fault_code_inlet_tempera=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.fault_code.bits.inlet_tempera));
    GBT27930_A_MSG_LOG("\t fault_code_cable_tempera=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.fault_code.bits.cable_tempera));
    GBT27930_A_MSG_LOG("\t fault_code_coupler=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.fault_code.bits.coupler));
    GBT27930_A_MSG_LOG("\t fault_code_batt_tempera=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.fault_code.bits.batt_tempera));
    GBT27930_A_MSG_LOG("\t fault_code_relay=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.fault_code.bits.relay));
    GBT27930_A_MSG_LOG("\t fault_code_cc2_volt=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.fault_code.bits.cc2_volt));
    GBT27930_A_MSG_LOG("\t fault_code_other=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.fault_code.bits.other));
    GBT27930_A_MSG_LOG("\t ");

    // GBT27930_A_MSG_LOG("\t error_code=[0x%02x]", msg->msg.bst.error_code.all);
    GBT27930_A_MSG_LOG("\t error_code_current=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.error_code.bits.current));
    GBT27930_A_MSG_LOG("\t error_code_voltage=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.error_code.bits.voltage));
    GBT27930_A_MSG_LOG("\t error_code_param=%s", enum_names_OpenChaoJi_gbt27930_a_FaultState(msg->msg.bst.error_code.bits.param));
}

static void OpenChaoJi_gbt27930_a_msg_log_bsd(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bsd");
    GBT27930_A_MSG_LOG("\t end_soc=%d(1%%)", msg->msg.bsd.end_soc);
    GBT27930_A_MSG_LOG("\t min_cellvolt=%d(0.01V)", msg->msg.bsd.min_cellvolt);
    GBT27930_A_MSG_LOG("\t max_cellvolt=%d(0.01V)", msg->msg.bsd.max_cellvolt);
    GBT27930_A_MSG_LOG("\t min_tempera=%d(1°C)", (int)msg->msg.bsd.min_tempera-50);
    GBT27930_A_MSG_LOG("\t max_tempera=%d(1°C)", (int)msg->msg.bsd.max_tempera-50);
}

static void OpenChaoJi_gbt27930_a_msg_log_bem(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    GBT27930_A_MSG_LOG("msg_bem");
    // GBT27930_A_MSG_LOG("\t tout_code=[0x%08x]", msg->msg.bem.tout_code.all);
    GBT27930_A_MSG_LOG("\t timeout_crm_00=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.bem.tout_code.bits.crm_00));
    GBT27930_A_MSG_LOG("\t timeout_crm_aa=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.bem.tout_code.bits.crm_aa));
    GBT27930_A_MSG_LOG("\t timeout_cml=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.bem.tout_code.bits.cml));
    GBT27930_A_MSG_LOG("\t timeout_cro=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.bem.tout_code.bits.cro));
    GBT27930_A_MSG_LOG("\t timeout_ccs=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.bem.tout_code.bits.ccs));
    GBT27930_A_MSG_LOG("\t timeout_cst=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.bem.tout_code.bits.cst));
    GBT27930_A_MSG_LOG("\t timeout_csd=%s", enum_names_OpenChaoJi_gbt27930_a_ErrorState(msg->msg.bem.tout_code.bits.csd));
}

/**
 * @function OpenChaoJi_gbt27930_a_msg_log
 * @brief 日志
 * @param msg 消息结构体
 * @return void
 */
extern void OpenChaoJi_gbt27930_a_msg_log(const struct OpenChaoJi_gbt27930_a_msg *msg)
{
    if (msg == NULL) {
        return;
    }

    switch (msg->pid) {
    case OPENCHAOJI_GBT27930_A_PGN_CHM: OpenChaoJi_gbt27930_a_msg_log_chm(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_CRM: OpenChaoJi_gbt27930_a_msg_log_crm(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_CTS: OpenChaoJi_gbt27930_a_msg_log_cts(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_CML: OpenChaoJi_gbt27930_a_msg_log_cml(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_CRO: OpenChaoJi_gbt27930_a_msg_log_cro(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_CCS: OpenChaoJi_gbt27930_a_msg_log_ccs(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_CST: OpenChaoJi_gbt27930_a_msg_log_cst(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_CSD: OpenChaoJi_gbt27930_a_msg_log_csd(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_CEM: OpenChaoJi_gbt27930_a_msg_log_cem(msg); break;

    case OPENCHAOJI_GBT27930_A_PGN_BHM: OpenChaoJi_gbt27930_a_msg_log_bhm(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BRM: OpenChaoJi_gbt27930_a_msg_log_brm(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BCP: OpenChaoJi_gbt27930_a_msg_log_bcp(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BRO: OpenChaoJi_gbt27930_a_msg_log_bro(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BCL: OpenChaoJi_gbt27930_a_msg_log_bcl(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BCS: OpenChaoJi_gbt27930_a_msg_log_bcs(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BSM: OpenChaoJi_gbt27930_a_msg_log_bsm(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BMV: OpenChaoJi_gbt27930_a_msg_log_bmv(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BMT: OpenChaoJi_gbt27930_a_msg_log_bmt(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BSP: OpenChaoJi_gbt27930_a_msg_log_bsp(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BST: OpenChaoJi_gbt27930_a_msg_log_bst(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BSD: OpenChaoJi_gbt27930_a_msg_log_bsd(msg); break;
    case OPENCHAOJI_GBT27930_A_PGN_BEM: OpenChaoJi_gbt27930_a_msg_log_bem(msg); break;
    default:
        return;
    }

    return;
}

/**
 * CMP_CPY类型
 */
bool OpenChaoJi_gbt27930_a_msg_cmpcpy_array(int tag, const char * name, uint8_t * dst, const uint8_t * src, int len)
{
    if (memcmp(dst, src, len) != 0)
    {
        LOG_STATUS_CHANGE("[%d]%s changed", tag, name);
        LOG_DATA_BUFF_CHANGE(dst, len);
        LOG_DATA_BUFF_CHANGE(src, len);

        memcpy(dst, src, len);
        return true;
    }

    return false;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(int tag, const char * name, uint8_t * dst, const uint8_t src)
{
    if (*dst != src)
    {
        LOG_STATUS_CHANGE("[%d]%s [%d]->[%d]", tag, name, *dst, src);

        *dst = src;
        return true;
    }

    return false;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(int tag, const char * name, uint16_t * dst, const uint16_t src)
{
    if (*dst != src)
    {
        LOG_STATUS_CHANGE("[%d]%s [%d]->[%d]", tag, name, *dst, src);

        *dst = src;
        return true;
    }

    return false;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_uint32(int tag, const char * name, uint32_t * dst, const uint32_t src)
{
    if (*dst != src)
    {
        LOG_STATUS_CHANGE("[%d]%s [%ld]->[%ld]", tag, name, *dst, src);

        *dst = src;
        return true;
    }

    return false;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_enum(int tag, const char * name, uint8_t * dst, const uint8_t src, const char *(enum_name_func)(int))
{
    if (*dst != src)
    {
        LOG_STATUS_CHANGE("[%d]%s [%s]->[%s]", tag, name, (*enum_name_func)(*dst), (*enum_name_func)(src));

        *dst = src;
        return true;
    }

    return false;
}

// SECC
bool OpenChaoJi_gbt27930_a_msg_cmpcpy_chm(int tag, struct OpenChaoJi_gbt27930_a_msg_chm *dst, const struct OpenChaoJi_gbt27930_a_msg_chm *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "pro_version", dst->pro_version, src->pro_version, 3)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_crm(int tag, struct OpenChaoJi_gbt27930_a_msg_crm *dst, const struct OpenChaoJi_gbt27930_a_msg_crm *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_enum(tag, "recognition_result", &dst->recognition_result, src->recognition_result, enum_names_OpenChaoJi_gbt27930_a_RecognizeType)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint32(tag, "charger_id", &dst->charger_id, src->charger_id)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "charger_location", dst->charger_location, src->charger_location, 3)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_cts(int tag, struct OpenChaoJi_gbt27930_a_msg_cts *dst, const struct OpenChaoJi_gbt27930_a_msg_cts *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "time", dst->time, src->time, 7)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_cml(int tag, struct OpenChaoJi_gbt27930_a_msg_cml *dst, const struct OpenChaoJi_gbt27930_a_msg_cml *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "max_output_voltage(0.1V)", &dst->max_output_voltage, src->max_output_voltage)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "min_output_voltage(0.1V)", &dst->min_output_voltage, src->min_output_voltage)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "max_output_current(0.1A, -400A)", &dst->max_output_current, src->max_output_current)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "min_output_current(0.1A, -400A)", &dst->min_output_current, src->min_output_current)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_cro(int tag, struct OpenChaoJi_gbt27930_a_msg_cro *dst, const struct OpenChaoJi_gbt27930_a_msg_cro *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_enum(tag, "secc_ready", &dst->charger_ready_for_charging, src->charger_ready_for_charging, enum_names_OpenChaoJi_gbt27930_a_ReadyType)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_ccs(int tag, struct OpenChaoJi_gbt27930_a_msg_ccs *dst, const struct OpenChaoJi_gbt27930_a_msg_ccs *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "output_voltage_value(0.1V)", &dst->output_voltage_value, src->output_voltage_value)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "output_current_value(0.1A, -400A)", &dst->output_current_value, src->output_current_value)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "cumulative_charging_time(1min)", &dst->cumulative_charging_time, src->cumulative_charging_time)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_enum(tag, "charging_permissible", &dst->state.all, src->state.bits.charging_permissible, enum_names_OpenChaoJi_gbt27930_a_PauseStatusType)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_cst(int tag, struct OpenChaoJi_gbt27930_a_msg_cst *dst, const struct OpenChaoJi_gbt27930_a_msg_cst *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "stop_code", &dst->stop_code.all, src->stop_code.all)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "fault_code", &dst->fault_code.all, src->fault_code.all)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "error_code", &dst->error_code.all, src->error_code.all)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_csd(int tag, struct OpenChaoJi_gbt27930_a_msg_csd *dst, const struct OpenChaoJi_gbt27930_a_msg_csd *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "cumulative_charging_time(1min)", &dst->cumulative_charging_time, src->cumulative_charging_time)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "output_energy(0.1kWh)", &dst->output_energy, src->output_energy)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint32(tag, "charger_id", &dst->charger_id, src->charger_id)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_cem(int tag, struct OpenChaoJi_gbt27930_a_msg_cem *dst, const struct OpenChaoJi_gbt27930_a_msg_cem *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint32(tag, "tout_code", &dst->tout_code.all, src->tout_code.all)) {
        changed = true;
    }

    return changed;
}

// EVCC
bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bhm(int tag, struct OpenChaoJi_gbt27930_a_msg_bhm *dst, const struct OpenChaoJi_gbt27930_a_msg_bhm *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "insul_request_voltage(0.1V)", &dst->insul_request_voltage, src->insul_request_voltage)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_brm(int tag, struct OpenChaoJi_gbt27930_a_msg_brm *dst, const struct OpenChaoJi_gbt27930_a_msg_brm *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "pro_version", dst->pro_version, src->pro_version, 3)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_enum(tag, "batt_type", &dst->batt_type, src->batt_type, enum_names_OpenChaoJi_gbt27930_a_BattType)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "rated_capacity(0.1Ah)", &dst->rated_capacity, src->rated_capacity)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "rated_voltage(0.1V)", &dst->rated_voltage, src->rated_voltage)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "batt_factory", dst->batt_factory, src->batt_factory, 4)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "batt_sn", dst->batt_sn, src->batt_sn, 4)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "batt_date_year(+1985)", &dst->batt_date_year, src->batt_date_year)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "batt_date_month", &dst->batt_date_month, src->batt_date_month)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "batt_date_day", &dst->batt_date_day, src->batt_date_day)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "charge_cycles", dst->charge_cycles, src->charge_cycles, 3)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_enum(tag, "batt_property", &dst->batt_property, src->batt_property, enum_names_OpenChaoJi_gbt27930_a_BattPropertyType)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "evin", dst->evin, src->evin, 17)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "sw_version", dst->sw_version, src->sw_version, 8)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bcp(int tag, struct OpenChaoJi_gbt27930_a_msg_bcp *dst, const struct OpenChaoJi_gbt27930_a_msg_bcp *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "allow_cellvolt(0.01V)", &dst->allow_cellvolt, src->allow_cellvolt)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "allow_current(0.1A, -400A)", &dst->allow_current, src->allow_current)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "rated_energy(0.1kWh)", &dst->rated_energy, src->rated_energy)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "allow_voltage(0.1V)", &dst->allow_voltage, src->allow_voltage)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "allow_tempera(1°C, -50°C)", &dst->allow_tempera, src->allow_tempera)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "batt_soc(0.1%%)", &dst->batt_soc, src->batt_soc)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "measured_voltage(0.1V)", &dst->measured_voltage, src->measured_voltage)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bro(int tag, struct OpenChaoJi_gbt27930_a_msg_bro *dst, const struct OpenChaoJi_gbt27930_a_msg_bro *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_enum(tag, "evcc_ready", &dst->bms_ready, src->bms_ready, enum_names_OpenChaoJi_gbt27930_a_ReadyType)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bcl(int tag, struct OpenChaoJi_gbt27930_a_msg_bcl *dst, const struct OpenChaoJi_gbt27930_a_msg_bcl *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;


    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "target_voltage(0.1V)", &dst->target_voltage, src->target_voltage)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "target_current(0.1A, -400A)", &dst->target_current, src->target_current)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_enum(tag, "charge_mode", &dst->charge_mode, src->charge_mode, enum_names_OpenChaoJi_gbt27930_a_ChargeModeType)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bcs(int tag, struct OpenChaoJi_gbt27930_a_msg_bcs *dst, const struct OpenChaoJi_gbt27930_a_msg_bcs *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "measured_voltage(0.1V)", &dst->measured_voltage, src->measured_voltage)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "measured_current(0.1A, -400A)", &dst->measured_current, src->measured_current)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "max_cellvolt", &dst->max_cellvolt.all, src->max_cellvolt.all)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "soc(1%%)", &dst->soc, src->soc)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "expected_time(1min)", &dst->expected_time, src->expected_time)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bsm(int tag, struct OpenChaoJi_gbt27930_a_msg_bsm *dst, const struct OpenChaoJi_gbt27930_a_msg_bsm *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "max_cellvolt_id(+1)", &dst->max_cellvolt_id, src->max_cellvolt_id)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "max_tempera(1°C, -50°C)", &dst->max_tempera, src->max_tempera)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "max_tempera_id(+1)", &dst->max_tempera_id, src->max_tempera_id)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "min_tempera(1°C, -50°C)", &dst->min_tempera, src->min_tempera)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "min_tempera_id(+1)", &dst->min_tempera_id, src->min_tempera_id)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "batt_state", &dst->batt_state.all, src->batt_state.all)) {
        changed = true;
    }
    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bmv(int tag, struct OpenChaoJi_gbt27930_a_msg_bmv *dst, const struct OpenChaoJi_gbt27930_a_msg_bmv *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "cellvolt", (uint8_t *)dst->cellvolt, (uint8_t *)src->cellvolt, sizeof(src->cellvolt))) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bmt(int tag, struct OpenChaoJi_gbt27930_a_msg_bmt *dst, const struct OpenChaoJi_gbt27930_a_msg_bmt *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "tempera", dst->tempera, src->tempera, sizeof(src->tempera))) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bsp(int tag, struct OpenChaoJi_gbt27930_a_msg_bsp *dst, const struct OpenChaoJi_gbt27930_a_msg_bsp *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    // if (OpenChaoJi_gbt27930_a_msg_cmpcpy_array(tag, "res", dst->res, src->res, sizeof(src->res))) {
    //     changed = true;
    // }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bst(int tag, struct OpenChaoJi_gbt27930_a_msg_bst *dst, const struct OpenChaoJi_gbt27930_a_msg_bst *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "stop_code", &dst->stop_code.all, src->stop_code.all)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "fault_code", &dst->fault_code.all, src->fault_code.all)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "error_code", &dst->error_code.all, src->error_code.all)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bsd(int tag, struct OpenChaoJi_gbt27930_a_msg_bsd *dst, const struct OpenChaoJi_gbt27930_a_msg_bsd *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;

    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "end_soc(1%%)", &dst->end_soc, src->end_soc)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "min_cellvolt(0.01V)", &dst->min_cellvolt, src->min_cellvolt)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint16(tag, "max_cellvolt(0.01V)", &dst->max_cellvolt, src->max_cellvolt)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "min_tempera(1°C, -50°C)", &dst->min_tempera, src->min_tempera)) {
        changed = true;
    }
    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint8(tag, "max_tempera(1°C, -50°C)", &dst->max_tempera, src->max_tempera)) {
        changed = true;
    }

    return changed;
}

bool OpenChaoJi_gbt27930_a_msg_cmpcpy_bem(int tag, struct OpenChaoJi_gbt27930_a_msg_bem *dst, const struct OpenChaoJi_gbt27930_a_msg_bem *src)
{
    if (src == NULL || dst == NULL)
    {
        return false;
    }

    bool changed = false;


    if (OpenChaoJi_gbt27930_a_msg_cmpcpy_uint32(tag, "tout_code", &dst->tout_code.all, src->tout_code.all)) {
        changed = true;
    }

    return changed;
}
#endif
